package com.yunji.order.context.engine;

import com.yunji.cabinet.device.DeviceInfoCache;
import com.yunji.coffee.entity.dto.DeviceCellDetailDTO;
import com.yunji.coffee.entity.dto.ICommonDeviceDetail;
import com.yunji.order.domain.OrderDetailDO;
import com.yunji.order.domain.OrderOrdinalDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;

import java.util.*;

/**
 * @author : peter-zhu
 * @date : 2025/4/2 18:08
 * @description : TODO
 **/
@Slf4j
public class OrderCellCalculate {
    public static class Grid {
        int ordinal, productNums;   // 格子号，格子商品数量
        long productId;
        String imei;

        public Grid(long productId, int ordinal, int productNums) {
            this.productId = productId;
            this.ordinal = ordinal;
            this.productNums = productNums;
        }

        public Grid(long productId, int ordinal, int productNums, String imei) {
            this.productId = productId;
            this.ordinal = ordinal;
            this.productNums = productNums;
            this.imei = imei;
        }
    }

    // 测试用例： OrderDetailDO 有商品ID和商品数量来模拟购买，Grid就是设备的格子，一个设备多个格子，格子有格子号，格子商品数量和商品数量。
    // 模拟购买返回的OrderOrdinalDO，期望OrderOrdinalDO能够算出设备每个格子被卖了多少数量，还剩下多少数量
    public static void main(String[] args) {
        // 模拟大卫生柜 格子号1：商品ID1 数量0 格子号2：商品ID1 数量2 格子号3：商品ID1 数量10 格子号4：商品ID2 数量4 格子号5：商品ID2 数量10
        List<Grid> grids = Arrays.asList(
                new Grid(1L, 1, 0), new Grid(1L, 2, 2), new Grid(1L, 3, 10),
                new Grid(2L, 4, 4), new Grid(2L, 5, 10)
        );
        // 模拟够买 商品ID为1 数量为8  商品ID为2 数量为5
        List<OrderDetailDO> buyerMsg = Arrays.asList(new OrderDetailDO(1L, 1), new OrderDetailDO(2L, 5));
        List<OrderOrdinalDO> result = purchase(grids, buyerMsg);
        result.forEach(System.out::println);
    }

    //-------------------以上是静态类部类和测试用例 以下才是真正实现-----------------
    public static List<OrderOrdinalDO> purchase(String imei, List<OrderDetailDO> buyerMsg) {
        List<ICommonDeviceDetail> detailList = DeviceInfoCache.getInfo(imei).getDetailList();
        List<Grid> grids = Lists.newArrayList();
        for (ICommonDeviceDetail detail : detailList) {
            DeviceCellDetailDTO cellDetail = detail.getCellDetail();
            int num = cellDetail.getProductNums();
            num = num > 1 ? num - 1 : num;
            if (num > 0) {
                Grid grid = new Grid(cellDetail.getProductId(), cellDetail.getOrdinal(), cellDetail.getProductNums(), imei);
                grids.add(grid);
            }
        }
        return purchase(grids, buyerMsg);
    }

    public static List<OrderOrdinalDO> purchase(List<Grid> grids, List<OrderDetailDO> buyerMsg) {
        // 1. 构建设备格子映射 (productId -> 优先队列<格子>)
        Map<Long, PriorityQueue<Grid>> stockMap = new HashMap<>();
        for (Grid g : grids) {
            stockMap.computeIfAbsent(g.productId, k -> new PriorityQueue<>(Comparator.comparingInt(x -> x.ordinal)))
                    .add(g);
        }
        List<OrderOrdinalDO> orderOrdinals = new ArrayList<>();
        for (OrderDetailDO orderDetail : buyerMsg) {
            PriorityQueue<Grid> pq = stockMap.get(orderDetail.getProductId());
            if (pq == null) continue;
            int remainingToBuy = orderDetail.getProductNums();
            // 2 货物不足日志(极端异常情况,因为订单支付时已经判断货物充足才支付)
            int totalAvailable = pq.stream().mapToInt(g -> g.productNums).sum();
            if (totalAvailable < remainingToBuy)
                log.error("商品 ID {} 库存不足！需要 {}，但只有 {}", orderDetail.getProductId(), remainingToBuy, totalAvailable);
            // 3. 处理购买逻辑 最终复杂度大约是
            while (remainingToBuy > 0 && !pq.isEmpty()) {
                Grid grid = pq.poll();
                int sold = Math.min(grid.productNums, remainingToBuy); // 该格子提供的数量
                remainingToBuy -= sold;
                grid.productNums -= sold; // 更新剩余库存
                // 记录销售情况
                OrderOrdinalDO orderOrdinalDO = new OrderOrdinalDO(orderDetail.getProductId(), grid.ordinal, sold, grid.productNums);
                orderOrdinalDO.setOrderId(orderDetail.getOrderId());
                orderOrdinalDO.setOrderCode(orderDetail.getOrderCode());
                orderOrdinalDO.setOrderDetailId(orderDetail.getOrderDetailId());
                orderOrdinalDO.setSku(orderDetail.getSku());
                orderOrdinalDO.setImei(grid.imei);
                orderOrdinals.add(orderOrdinalDO);
                // 如果格子仍有库存,重新放入队列
                if (grid.productNums > 0) {
                    pq.add(grid);
                }
            }
        }
        return orderOrdinals;
    }
//        Map<Long, PriorityQueue<Grid>> stockMap = Maps.newHashMap();
//        for (Grid g : grids) {
//            stockMap.computeIfAbsent(g.productId, k -> new PriorityQueue<>(Comparator.comparingInt(x -> x.ordinal))).add(g);
//        }
//        List<OrderOrdinalDO> orderOrdinals = Lists.newArrayList();
//        for (OrderDetailDO p : buyerMsg) {
//            PriorityQueue<Grid> pq = stockMap.get(p.getProductId());
//            if (pq == null) continue;
//            int remainingToBuy = p.getProductNums();
//            List<int[]> usage = Lists.newArrayList();
//            int totalAvailable = pq.stream().mapToInt(g -> g.productNums).sum();
//            if (totalAvailable < remainingToBuy)
//                log.error("商品 ID {} 库存不足！需要 {}，但只有 {}", p.getProductId(), remainingToBuy, totalAvailable);
//            while (remainingToBuy > 0 && !pq.isEmpty()) {
//                Grid grid = pq.poll();
//                int used = Math.min(grid.productNums, remainingToBuy);
//                usage.add(new int[]{grid.ordinal, used});
//                remainingToBuy -= used;
//                grid.productNums -= used;
//                if (grid.productNums > 0) pq.add(grid);
//                orderOrdinals.add(new OrderOrdinalDO(p.getProductId(), grid.ordinal, used, grid.productNums));
//            }
//        }
}
